home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Libraries / Log Library 1.01 / LogLibComponent ƒ / LogLibComponent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-03  |  20.6 KB  |  976 lines  |  [TEXT/KAHL]

  1. /*
  2.     LogLibComponent.c
  3.     
  4.     Code version 1.01
  5.     
  6.     This is the source for a log file component.  For those of you who don't know what a component is, read
  7.     the Component.note file.
  8.     
  9.     5/7/94 dn - Created.
  10.     7/3/94 dn - Modified to work with the Universal Headers.
  11. */
  12.  
  13. //#define DEBUGIT 2
  14.  
  15. #include <Packages.h>
  16.  
  17. #include "LogLibComponent Private.h"
  18.  
  19. /*
  20.     Local prototypes, macros, definitions, etc.
  21.     
  22. */
  23.  
  24. // a few macros to make our lives seem easier...
  25. #if NEW_HEADERS_AVAILABLE
  26. #define mCCFWS(x)    CallComponentFunctionWithStorage(storage,params,(ComponentFunctionUPP)x)
  27. #define mCCF(x)    CallComponentFunction(params,(ComponentFunctionUPP)x)
  28. #else
  29. #define mCCFWS(x)    CallComponentFunctionWithStorage(storage,params,(ComponentFunction)x)
  30. #define mCCF(x)    CallComponentFunction(params,(ComponentFunction)x)
  31. #endif
  32.  
  33. #define mSetChar(a,b)    (*(a) = b); a++
  34. #define mSetCharV(a,b)    (*(a) = (b+'0'));a++
  35.  
  36. #define fsDontCache            0x20
  37.  
  38. // define the HandleState type
  39. typedef char HandleState;
  40.  
  41. // prototypes for the local functions.
  42. HandleState LockHandle(Handle h);
  43. void UnlockHandle(Handle h,HandleState state);
  44. OSErr CloseLog(LogLibHdl mem);
  45. OSErr TryCloseLog(LogLibHdl mem);
  46. ComponentResult VerifyTypeCreator(Handle storage);
  47. ComponentResult OpenTheLogFile(Handle storage);
  48. OSErr FSWriteNoCache(short refnum, long *count_p, const Ptr buffer_p);
  49. OSErr LogData(Handle storage,char* data);
  50. OSErr LogCR(Handle storage);
  51. OSErr FSFlushFile(short fref);
  52. OSErr LogTheTime(Handle storage);
  53. char* AddIntToBuf(char* buf,char val);
  54.  
  55. /*
  56.     And now back to our main program...
  57.     
  58. */
  59.  
  60. /*
  61.     main or _LogDispatch
  62.     
  63.     Component dispatch routine.  Depending on whether the DEBUGIT flag is set, this will either
  64.     compile to the main function routine or a simple dispatch routine to be passed the the component
  65.     manager's RegisterComponent routine.
  66. */
  67. #ifdef DEBUGIT
  68. pascal ComponentResult _LogDispatch(ComponentParameters* params, Handle storage){
  69. #else
  70. pascal ComponentResult main(ComponentParameters* params,Handle storage){
  71. #endif
  72.  
  73.     ComponentResult cres=noErr;
  74.     
  75.     switch (params->what){    // switch to call the appropriate routine based on the value of the routine to call
  76.         
  77.         case kComponentOpenSelect:        // open request
  78.         
  79.             cres=mCCFWS(_LogOpen);
  80.             break;
  81.         
  82.         case kComponentCloseSelect:        // close
  83.             
  84.             cres=mCCFWS(_LogClose);
  85.             break;
  86.             
  87.         case kComponentCanDoSelect:        // cando
  88.             
  89.             cres=mCCF(_LogCanDo);
  90.             break;
  91.             
  92.         case kComponentVersionSelect:        // version
  93.             
  94.             cres=mCCF(_LogVersion);
  95.             break;
  96.             
  97.         case kComponentTargetSelect:        // target
  98.             
  99.             cres=mCCFWS(_LogTarget);
  100.             break;
  101.             
  102.         case kComponentRegisterSelect:    // register
  103.             
  104.             cres=mCCFWS(_LogRegister);
  105.             break;
  106.             
  107.         case kLogStorage:                // return the internal storage
  108.             
  109.             cres=mCCFWS(_LogStorage);
  110.             break;
  111.             
  112.         case kLogDefaults:                // change the defaults
  113.             
  114.             cres=mCCFWS(_LogDefaults);
  115.             break;
  116.             
  117.         case kLogSetup:                // set up the log file
  118.             
  119.             cres=mCCFWS(_LogSetup);
  120.             break;
  121.             
  122.         case kLogSetupFSp:                // set up the log file using a FSSpec
  123.             
  124.             cres=mCCFWS(_LogSetupFSp);
  125.             break;
  126.             
  127.         case kLogText:                    // log some C-style text
  128.             
  129.             cres=mCCFWS(_LogText);
  130.             break;
  131.             
  132.         case kLogTime:                    // log some C-style text prepended by the time and date
  133.             
  134.             cres=mCCFWS(_LogTime);
  135.             break;
  136.         
  137.         case kLogPText:                // log some Pascal style text
  138.         
  139.             cres=mCCFWS(_LogPText);
  140.             break;
  141.         
  142.         case kLogPTime:                // log some Pascal style text prepended by the date and time
  143.             
  144.             cres=mCCFWS(_LogPTime);
  145.             break;
  146.             
  147.         case kLogWrite:                // log some data to the log file
  148.             
  149.             cres=mCCFWS(_LogWrite);
  150.             break;
  151.         
  152.         default:                        // invalid selector code
  153.             
  154.             cres=paramErr;
  155.             break;
  156.     }
  157.     
  158.     return cres;
  159. }
  160.  
  161. /*
  162.     LogOpen
  163.     
  164.     Handles the opening of the log component.  This allocates the internal memory that we will be using and
  165.     initializes it for us.
  166. */
  167. pascal ComponentResult _LogOpen(Handle storage,ComponentInstance self){
  168.     ComponentResult cres=noErr;
  169.     LogLibHdl mem;
  170.     LogLibPtr mp;
  171.     short ourResFork;
  172.     
  173.     HandleState hs;
  174.     
  175.     mem=(LogLibHdl)NewHandleClear(sizeof(LogLibRec));        // allocate the memory;
  176.     
  177.     if (mem==(LogLibHdl)0){                                // then there was a problem...
  178.         cres=MemError();
  179.         
  180.         return cres;
  181.     }
  182.     
  183.     ourResFork=OpenComponentResFile((Component)self);        // open the resource file
  184.     
  185.     // lock down our memory...
  186.     hs=LockHandle((Handle)mem);
  187.     mp=*mem;
  188.     
  189.     // initialize our values...
  190.     
  191.     mp->logSpec.vRefNum=0;
  192.     mp->logSpec.parID=0;
  193.     
  194.     mp->fileRefNum=-1;                                    // indicates that the file is not open
  195.     
  196.     mp->inited=false;
  197.     
  198.     // setup default values...
  199.     mp->keepLogOpen=false;
  200.     mp->savedValue=false;
  201.     mp->wasOpened=false;
  202.     
  203.     mp->creator='R*ch';
  204.     mp->type='TEXT';
  205.     
  206.     // initialize the standard stuff...
  207.     mp->self=(Component)self;
  208.     mp->kidnapper=(ComponentInstance)0;
  209.     mp->delegate=(Component)0;
  210.     mp->delegated=(ComponentInstance)0;
  211.     mp->resFileRefNum=ourResFork;
  212.     
  213.     // unlock the memory
  214.     UnlockHandle((Handle)mem,hs);
  215.     
  216.     SetComponentInstanceStorage(self,(Handle)mem);            // save the storage just created.
  217.     
  218.     return cres;
  219. }
  220.  
  221. /*
  222.     _LogClose
  223.     
  224.     Closes the log file if it is open.  It also disposes of our storage before going away.
  225. */
  226. pascal ComponentResult _LogClose(Handle storage,ComponentInstance self){
  227.     ComponentResult cres=noErr;
  228.     LogLibHdl mem=(LogLibHdl)storage;
  229.     HandleState hs;
  230.     
  231.     hs=LockHandle((Handle)mem);
  232.     CloseComponentResFile((*mem)->resFileRefNum);            // close the resource file
  233.     
  234.     UnlockHandle((Handle)mem,hs);    
  235.     
  236.     cres=(ComponentResult)CloseLog(mem);                    // close the log file
  237.     
  238.     DisposeHandle(storage);                                // get rid of the internal storage
  239.     
  240.     return cres;
  241. }
  242.  
  243. /*
  244.     _LogRegister
  245.     
  246.     Handles the registration message.  This message is only received once, during system startup when the
  247.     Component Manager does it's 'thng's. ;-)
  248.     
  249.     So this is where we put the code to display our little icon.  Isn't that special?
  250.     
  251.     The icon is not displayed (and the code is not needed) if the DEBUGIT flag is set.
  252. */
  253. pascal ComponentResult _LogRegister(Handle storage,ComponentInstance self){
  254.     ComponentResult cres=noErr;
  255.     LogLibHdl mem=(LogLibHdl)storage;
  256.     HandleState hs;
  257.  
  258. #ifndef DEBUGIT
  259.     extern void ComponentShowInit(void);
  260.     
  261.     hs=LockHandle((Handle)mem);
  262.     
  263.     UseResFile((*mem)->resFileRefNum);
  264.     
  265.     ComponentShowInit();
  266.     
  267.     UnlockHandle((Handle)mem,hs);
  268.  
  269. #endif
  270.  
  271.     return cres;
  272. }
  273.  
  274. /*
  275.     _LogTarget
  276.     
  277.     This message is received when another component is capturing us.  We don't really do much besides save
  278.     their instance.
  279. */
  280. pascal ComponentResult _LogTarget(Handle storage,ComponentInstance kidnapper){
  281.     ComponentResult cres=noErr;
  282.     LogLibHdl mem=(LogLibHdl)storage;
  283.     HandleState hs;
  284.     
  285.     hs=LockHandle((Handle)mem);
  286.     
  287.     (*mem)->kidnapper=kidnapper;
  288.     
  289.     UnlockHandle((Handle)mem,hs);
  290.     
  291.     return cres;
  292. }
  293.  
  294. /*
  295.     _LogCanDo
  296.     
  297.     Determines if the log component can do the function selector requested.  Returns true if it can, false if not.
  298. */
  299. pascal ComponentResult _LogCanDo(short selector){
  300.     ComponentResult cres=noErr;
  301.     
  302.     switch(selector){
  303.         case kComponentOpenSelect:    // open request
  304.         case kComponentCloseSelect:
  305.         case kComponentCanDoSelect:
  306.         case kComponentVersionSelect:
  307.         case kComponentTargetSelect:
  308.         case kComponentRegisterSelect:
  309.         case kLogStorage:
  310.         case kLogDefaults:
  311.         case kLogSetup:
  312.         case kLogSetupFSp:
  313.         case kLogText:
  314.         case kLogTime:
  315.         case kLogWrite:
  316.         
  317.             cres=(ComponentResult)true;            // yes, we can do the above functions
  318.             break;
  319.             
  320.         default:
  321.             
  322.             cres=(ComponentResult)false;            // no, an invalid or unsupported selector code
  323.             break;
  324.     }
  325.     return cres;
  326. }
  327.  
  328. /*
  329.     _LogVersion
  330.     
  331.     Returns the version of the component.
  332. */
  333. pascal ComponentResult _LogVersion(void){
  334.     ComponentResult cres=noErr;
  335.     
  336.     cres=(ComponentResult)kLogLibComponentVersion;
  337.     
  338.     return cres;
  339. }
  340.  
  341. /*
  342.     _LogStorage
  343.     
  344.     Returns a handle to the components internal storage.
  345. */
  346. pascal ComponentResult _LogStorage(Handle storage){
  347.     ComponentResult cres=noErr;
  348.     
  349.     cres=(ComponentResult)storage;
  350.     
  351.     return cres;
  352. }
  353.  
  354. /*
  355.     _LogDefaults
  356.     
  357.     Changes the defaults for the log file.  If the file already exists, we should find and make the changes anyway.
  358. */
  359. pascal ComponentResult _LogDefaults(Handle storage,OSType creator,OSType type,Boolean keepOpen){
  360.     ComponentResult cres=noErr;
  361.     LogLibHdl mem=(LogLibHdl)storage;
  362.     LogLibPtr mp;
  363.     HandleState hs;
  364.     
  365.     hs=LockHandle((Handle)mem);
  366.     
  367.     mp=*mem;
  368.     
  369.     mp->creator=creator;
  370.     mp->type=type;
  371.     mp->keepLogOpen=keepOpen;
  372.     
  373.     cres=VerifyTypeCreator(storage);
  374.     
  375.     UnlockHandle((Handle)mem,hs);
  376.     
  377.     if (keepOpen){
  378.         cres=OpenTheLogFile(storage);
  379.     } else
  380.         cres=TryCloseLog(mem);
  381.     
  382.     return cres;
  383. }
  384.  
  385. /*
  386.     _LogSetup
  387.     
  388.     Sets up the FSSpec for the log file.
  389. */
  390. pascal ComponentResult _LogSetup(Handle storage,StringPtr name,short vref,long dirid){
  391.     ComponentResult cres=noErr;
  392.     LogLibHdl mem=(LogLibHdl)storage;
  393.     LogLibPtr mp;
  394.     HandleState hs;
  395.     
  396.     hs=LockHandle((Handle)mem);
  397.     mp=*mem;
  398.     
  399.     // we can only do this if the file is not open...
  400.     if (mp->fileRefNum!=-1){
  401.         UnlockHandle((Handle)mem,hs);
  402.         return paramErr;
  403.     }
  404.     
  405.     // now we have to set up the true fsspec in the global
  406.     // we don't use the FSMakeFSSpec call because I am not sure if the string is copied or just a pointer
  407.     // to the string is used (we need a copy so that it will stay around)...
  408.     BlockMove(name,(Ptr)(mp->logSpec.name),(name[0])+1);
  409.     mp->logSpec.parID=dirid;
  410.     mp->logSpec.vRefNum=vref;
  411.     
  412.     
  413.     if ((cres==noErr)||(cres==fnfErr)){
  414.         mp->inited=true;
  415.         mp->wasOpened=false;
  416.     }
  417.     
  418.     UnlockHandle((Handle)mem,hs);
  419.     
  420.     return cres;
  421. }
  422.  
  423. /*
  424.     _LogSetupFSp
  425.     
  426.     Use the FSSpec that the user is passing to the routine.
  427. */
  428. pascal ComponentResult _LogSetupFSp(Handle storage,FSSpec* fsp){
  429.     ComponentResult cres=noErr;
  430.     LogLibHdl mem=(LogLibHdl)storage;
  431.     LogLibPtr mp;
  432.     HandleState hs;
  433.     
  434.     hs=LockHandle((Handle)mem);
  435.     mp=*mem;
  436.     
  437.     // we can only do this if the file is not open...
  438.     if (mp->fileRefNum!=-1){
  439.         UnlockHandle((Handle)mem,hs);
  440.         return paramErr;
  441.     }
  442.     
  443.     // copy their fsspec into ours.
  444.     BlockMove((Ptr)fsp->name,(Ptr)(mp->logSpec.name),(fsp->name[0])+1);
  445.     mp->logSpec.parID=fsp->parID;
  446.     mp->logSpec.vRefNum=fsp->vRefNum;
  447.     
  448.     mp->inited=true;
  449.     mp->wasOpened=false;
  450.     
  451.     UnlockHandle((Handle)mem,hs);
  452.     
  453.     return cres;
  454. }
  455.  
  456. /*
  457.     _LogText
  458.     
  459.     Add some text to the log file.
  460. */
  461. pascal ComponentResult _LogText(Handle storage,char* buffer){
  462.     ComponentResult cres=noErr;
  463.     LogLibHdl mem=(LogLibHdl)storage;
  464.     LogLibPtr mp;
  465.     HandleState hs;
  466.     
  467.     hs=LockHandle((Handle)mem);
  468.     mp=*mem;
  469.     
  470.     cres=(ComponentResult)LogData(storage,buffer);
  471.         
  472.     UnlockHandle((Handle)mem,hs);
  473.     
  474.     return cres;
  475. }
  476.  
  477. /*
  478.     _LogTime
  479.     
  480.     Same as above but it adds the time to the file first. (no carriage return).
  481. */
  482. pascal ComponentResult _LogTime(Handle storage,char* buffer){
  483.     ComponentResult cres=noErr;
  484.     LogLibHdl mem=(LogLibHdl)storage;
  485.     LogLibPtr mp;
  486.     HandleState hs;
  487.     
  488.     hs=LockHandle((Handle)mem);
  489.     mp=*mem;
  490.     
  491.     cres=LogTheTime(storage);
  492.     
  493.     if (cres==noErr){    // then we can log the data...
  494.         
  495.         cres=(ComponentResult)LogData(storage,buffer);
  496.         
  497.     }
  498.     
  499.     UnlockHandle((Handle)mem,hs);
  500.     
  501.     return cres;
  502. }
  503.  
  504. /*
  505.     _LogPText and _LogPTime
  506.     
  507.     Used for printing pascal type strings.
  508. */
  509. pascal ComponentResult _LogPText(Handle storage,unsigned char* buf){
  510.     long size;
  511.     unsigned char cs=buf[0],*cp=buf+1;
  512.     
  513.     size=0L;size += cs; // convert the size to a long
  514.     
  515.     return _LogWrite(storage,&size,(Ptr)cp);
  516. }
  517.  
  518. pascal ComponentResult _LogPTime(Handle storage,unsigned char* buf){
  519.     long size;
  520.     unsigned char cs=buf[0],*cp=buf+1;
  521.     OSErr err;
  522.     
  523.     size=0L;size += cs;            // convert the size to a long
  524.     
  525.     err=LogTheTime(storage);    // first log the time
  526.     
  527.     if (err==noErr)                // continue to write the text
  528.         err=_LogWrite(storage,&size,(Ptr)cp);
  529.     
  530.     return err;
  531. }
  532.  
  533. /*
  534.     _LogWrite
  535.     
  536.     Like FSWrite, this procedure writes a buffer of text to the log file.
  537. */
  538. pascal ComponentResult _LogWrite(Handle storage,long* size,Ptr buffer){
  539.     ComponentResult ret=noErr;
  540.     LogLibHdl mem=(LogLibHdl)storage;
  541.     LogLibPtr mp;
  542.     HandleState hs;
  543.     
  544.     hs=LockHandle((Handle)mem);
  545.     mp=*mem;
  546.     
  547.     if (mp->fileRefNum==-1){                            // then the file is not open, open it now
  548.         ret=OpenTheLogFile(storage);
  549.     }
  550.     
  551.     if (ret==noErr)                                    // then write the text
  552.         ret=FSWriteNoCache(mp->fileRefNum,size,buffer);    // don't use the cache...
  553.     
  554.     TryCloseLog(mem);                                // close the log if it can be closed
  555.     
  556.     UnlockHandle((Handle)mem,hs);
  557.     
  558.     return ret;
  559. }
  560.  
  561.  
  562. /*•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••*\
  563.  
  564.                                     UTILITY FUNCTIONS
  565.                                     
  566. \*•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••*/
  567.  
  568. /*
  569.     HandleLock
  570.     
  571.     Locks a handle down, but returns the state that the handle was in previously (for resetting later...)
  572. */
  573. HandleState LockHandle(Handle h){
  574.     HandleState st;
  575.     
  576.     st=HGetState(h);                // get the current state of the handle
  577.     
  578.     HLock(h);                        // lock it down
  579.     
  580.     return st;                        // return the state
  581. }
  582.  
  583. /*
  584.     UnlockHandle
  585.     
  586.     Unlocks a handle, but resets it to the previous setting.
  587. */
  588. void UnlockHandle(Handle h,HandleState state){
  589.     
  590.     HUnlock(h);                    // unlock the handle
  591.     
  592.     HSetState(h,state);                // reset the state to the stored state
  593. }
  594.  
  595. /*
  596.     CloseLog
  597.     
  598.     Closes the log if it is open...
  599.     
  600.     Even though we are using a version of PBWrite that should allow us to write the file without having
  601.     to worry about the cache, there are two FlushVol calls in here just to ensure that everything is flushed
  602.     completely.
  603. */
  604. OSErr CloseLog(LogLibHdl mem){
  605.     OSErr cres=noErr;
  606.     LogLibPtr mp;
  607.     HandleState hs;
  608.     
  609.     hs=LockHandle((Handle)mem);
  610.     mp=*mem;
  611.     
  612.     if (mp->inited){    // then the FSSpec was initialized, check to see if the file is open
  613.         if (mp->fileRefNum!=-1){    // then the file is still open...
  614.             
  615.             // we will flush the file to ensure that everything is written out before closing...
  616.             cres=FlushVol((StringPtr)0,mp->logSpec.vRefNum);
  617.             
  618.             // close the file
  619.             FSClose(mp->fileRefNum);
  620.             
  621.             // again, just to be sure...
  622.             cres=FlushVol((StringPtr)0,mp->logSpec.vRefNum);
  623.             
  624.             mp->fileRefNum=-1;    // reset the refnum to -1 to indicate the file is closed.
  625.         }
  626.     }
  627.     
  628.     UnlockHandle((Handle)mem,hs);
  629.     
  630.     return cres;
  631. }
  632.  
  633. /*
  634.     TryCloseLog
  635.     
  636.     Only close the log if it can be closed (i.e. it should not if the keepLogOpen flag is set).
  637. */
  638. OSErr TryCloseLog(LogLibHdl mem){
  639.     LogLibPtr mp;
  640.     HandleState hs;
  641.     OSErr err=paramErr;
  642.     
  643.     hs=LockHandle((Handle)mem);
  644.     mp=*mem;
  645.     
  646.     if (!(mp->keepLogOpen))        // if we can close the file,
  647.         err=CloseLog(mem);        // then close it
  648.     
  649.     UnlockHandle((Handle)mem,hs);
  650.     
  651.     return err;
  652. }
  653.  
  654. /*
  655.     VerifyTypeCreator
  656.     
  657.     Called when a change is made to the type/creator of the log file as well as the first time this component
  658.     opens the file (to make sure everything is as it should be).
  659. */
  660. ComponentResult VerifyTypeCreator(Handle storage){
  661.     OSErr cres=noErr;
  662.     LogLibHdl mem=(LogLibHdl)storage;
  663.     LogLibPtr mp;
  664.     HandleState hs;
  665.     
  666.     hs=LockHandle((Handle)mem);
  667.     
  668.     mp=*mem;
  669.     
  670.     if (mp->inited){ // then the FSSpec is valid, it is possibly an existing file that we should change the stuff for.
  671.         FInfo info;
  672.         
  673.         cres=FSpGetFInfo(&(mp->logSpec),&info);    // get the info for the file
  674.         
  675.         if (cres==noErr){    // make the changes...
  676.             
  677.             if ((info.fdType!=mp->type)||(info.fdCreator!=mp->creator)){    // but only if they are different
  678.                 info.fdType=mp->type;
  679.                 info.fdCreator=mp->creator;                // reset to the new type and creator
  680.                 
  681.                 cres=FSpSetFInfo(&(mp->logSpec),&info);    // make the changes
  682.             }
  683.         }
  684.         
  685.         if (cres==fnfErr){    // then the file doesn't exist yet
  686.             cres=noErr;    // but that's ok
  687.         }
  688.         
  689.     }
  690.     
  691.     UnlockHandle((Handle)mem,hs);
  692.     
  693.     return (ComponentResult)cres;
  694. }
  695.  
  696. /*
  697.     OpenTheLogFile
  698.     
  699.     Opens the log file based on the stored FSSpec and sets the file pointer to the end of the file so that we
  700.     can start appending.  This should also set the cache bit thingy so that our stuff is not cached.
  701. */
  702. ComponentResult OpenTheLogFile(Handle storage){
  703.     OSErr cres=noErr;
  704.     LogLibHdl mem=(LogLibHdl)storage;
  705.     LogLibPtr mp;
  706.     HandleState hs;
  707.     
  708.     hs=LockHandle((Handle)mem);
  709.     
  710.     mp=*mem;
  711.     
  712.     // cannot do it if the fsspec hasn't been set up...
  713.     if (mp->inited==false){
  714.         UnlockHandle((Handle)mem,hs);
  715.         return paramErr;
  716.     }
  717.  
  718.     if (mp->fileRefNum!=-1){    // then the file is already open
  719.         UnlockHandle((Handle)mem,hs);
  720.         return noErr;
  721.     }
  722.     
  723.     if (!(mp->wasOpened)){    // if the file hasn't been opened before this component was created, then...
  724.         VerifyTypeCreator(storage);    // it may exist but it also may need the type/creator changed
  725.         mp->wasOpened=true;        // flag this as having been done.
  726.     }
  727.     
  728.     // ok, now use our FSSpec to open the file...
  729.     cres=FSpOpenDF(&(mp->logSpec),fsWrPerm,&(mp->fileRefNum));
  730.     
  731.     if (cres==fnfErr){    // then the file hasn't been created yet...
  732.         cres=FSpCreate(&(mp->logSpec),mp->creator,mp->type,smSystemScript);    // create it
  733.         
  734.         if (cres==noErr)                                                // it was created
  735.             cres=FSpOpenDF(&(mp->logSpec),fsWrPerm,&(mp->fileRefNum));        // open it again
  736.     }
  737.     
  738.     if (cres!=noErr){                // the file couldn't be opened, mark us as being closed
  739.         mp->fileRefNum=-1;
  740.     } else {    // move the file pointer to the end of the file so that we can begin appending...
  741.         cres=SetFPos(mp->fileRefNum,fsFromLEOF,0);
  742.     }
  743.     
  744.     UnlockHandle((Handle)mem,hs);
  745.     
  746.     return (ComponentResult)cres;
  747. }
  748.  
  749. /*
  750.     FSWriteNoCache
  751.     
  752.     Writes to the disk without caching the information (which can speed things up somewhat...).
  753. */
  754. OSErr FSWriteNoCache(short refnum, long *count_p, const Ptr buffer_p){
  755.     OSErr retcode;
  756.     ParamBlockRec pb;
  757.     
  758.     pb.ioParam.ioCompletion = 0;
  759.     pb.ioParam.ioRefNum = refnum;
  760.     pb.ioParam.ioBuffer = buffer_p;
  761.     pb.ioParam.ioReqCount = *count_p;
  762.     pb.ioParam.ioPosMode = fsAtMark | fsDontCache; 
  763.     pb.ioParam.ioPosOffset = 0;
  764.     
  765.     retcode = PBWrite(&pb, false);
  766.     
  767.     *count_p = pb.ioParam.ioActCount;
  768.     
  769.     return retcode;
  770. }
  771.  
  772. /*
  773.     LogData
  774.     
  775.     Writes the data out to the log file (it has to be open before we get here.
  776. */
  777. OSErr LogData(Handle storage,char* data){
  778.     long count=0L;
  779.     Ptr pt=(Ptr)data;
  780.     char* cp=data;
  781.     LogLibHdl mem=(LogLibHdl)storage;
  782.     LogLibPtr mp;
  783.     HandleState hs;
  784.     OSErr ret=noErr;
  785.     
  786.     hs=LockHandle((Handle)mem);
  787.     mp=*mem;
  788.     
  789.     if (mp->fileRefNum==-1){        // then open the file
  790.         ret=OpenTheLogFile(storage);
  791.     }
  792.     
  793.     while (*cp){                // calculate the size of the data to be written
  794.         count++;
  795.         cp++;
  796.     }
  797.     
  798.     if (ret==noErr)                // then it is ok to write the data
  799.         ret=FSWriteNoCache(mp->fileRefNum,&count,pt);
  800.     
  801.     TryCloseLog(mem);            // try to close the file
  802.     
  803.     UnlockHandle ((Handle)mem,hs);
  804.     
  805.     return ret;
  806. }
  807.  
  808. /*
  809.     LogCR
  810.     
  811.     Outputs a carriage return to the log file.
  812. */
  813. OSErr LogCR(Handle storage){
  814.     char data[20];
  815.     
  816.     data[0]=kNewLine;
  817.     data[1]=0;
  818.     
  819.     return LogData(storage,data);
  820. }
  821.  
  822. /*
  823.     FSFlushFile
  824.     
  825.     Flushes a file out to disk.
  826. */
  827. OSErr FSFlushFile(short fref){
  828.     OSErr ret;
  829.     IOParam pb;
  830.     
  831.     pb.ioCompletion=(ProcPtr)0;
  832.     pb.ioRefNum=fref;
  833.     
  834.     ret=PBFlushFile((ParmBlkPtr)&pb,false);
  835.     
  836.     return ret;
  837. }
  838.  
  839. /*
  840.     LogTheTime
  841.     
  842.     Outputs the time to the file.
  843. */
  844. OSErr LogTheTime(Handle storage){
  845.     char* timebuf;    // temp storage for putting the time into...
  846.     DateTimeRec dtr;
  847.     char ampm;
  848.     short hour,year;
  849.     char a,b,c,d,e,f;
  850.     OSErr cres;
  851.     char* cp1,*cp2;
  852.     
  853.     timebuf=(char*)NewPtr(100);
  854.     
  855.     if (timebuf!=(char*)0){    // then the space was allocated, ok to procede...
  856.         GetTime(&dtr);
  857.         
  858.         ampm=(dtr.hour < 12)?('a'):('p');    // choose either am or pm based on the hour
  859.         
  860.         hour=dtr.hour;    // recalculate the hour so it is in 12 hour mode.
  861.         
  862.         if (hour<13){
  863.             if (hour<1)
  864.                 hour=12;
  865.         } else {
  866.             hour -= 12;
  867.         }
  868.         
  869.         if (hour<1)
  870.             hour=12;
  871.         else
  872.         if (hour>12){
  873.             hour -=12;
  874.             ampm='p';
  875.         }
  876.         
  877.         year=dtr.year;        // calculate the year so that it is only the last 2 digits
  878.         if (year>100)
  879.             year %=100;
  880.         
  881.         // temp storage
  882.         a=dtr.month;
  883.         b=dtr.day;
  884.         c=year;
  885.         d=hour;
  886.         e=dtr.minute;
  887.         f=dtr.second;
  888.         
  889.         // print it to the buffer
  890.         cp1=AddIntToBuf(timebuf,a);
  891.         mSetChar(cp1,'/');cp2=cp1;
  892.         
  893.         cp1=AddIntToBuf(cp2,b);
  894.         mSetChar(cp1,'/');cp2=cp1;
  895.         
  896.         cp1=AddIntToBuf(cp2,c);
  897.         mSetChar(cp1,'\t');cp2=cp1;
  898.         
  899.         cp1=AddIntToBuf(cp2,d);
  900.         mSetChar(cp1,':');cp2=cp1;
  901.         
  902.         cp1=AddIntToBuf(cp2,e);
  903.         mSetChar(cp1,':');cp2=cp1;
  904.         
  905.         cp1=AddIntToBuf(cp2,f);
  906.         mSetChar(cp1,' ');
  907.         
  908.         mSetChar(cp1,ampm);mSetChar(cp1,'m');mSetChar(cp1,'\t');mSetChar(cp1,0);
  909.         
  910.         // write it to the file
  911.         cres=(ComponentResult)LogData(storage,timebuf);
  912.         
  913.         // get rid of the temporary buffer.
  914.         DisposePtr((Ptr)timebuf);
  915.     } else {
  916.         cres=MemError();
  917.     }
  918.  
  919.     return cres;
  920. }
  921.  
  922. /*
  923.     AddIntToBuf
  924.     
  925.     Adds a character integer to the buffer (two places only). [i.e. this is a small itoa()]
  926. */
  927. char* AddIntToBuf(char* buf,char val){
  928.     
  929.     if (val>99){    // ensure that we are only 2 digits...
  930.         val %= 100;
  931.     }
  932.     
  933.     if (val<10){    // special case if less than 10, need to print a zero first...
  934.         
  935.         mSetChar(buf,'0');
  936.         mSetCharV(buf,val);
  937.         
  938.     } else { // 2 digit number...
  939.         char a;
  940.         
  941.         a = val % 10;    // the lower number
  942.         val /= 10;    // the higher number
  943.         
  944.         mSetCharV(buf,val);
  945.         mSetCharV(buf,a);
  946.     }
  947.     
  948.     return buf;
  949. }
  950.  
  951. #ifdef DEBUGIT
  952.  
  953. void DumbTest(void);
  954.  
  955. /*
  956.     DumbTest
  957.     
  958.     Dummy routine which gets us over here from the test routines.  To switch files in the TPM debugger,
  959.     a call must actually be made to a function in that file.  This routine provides this function (the component
  960.     manager intercepts and processes all of the calls so the debugger never gets into the file without this
  961.     function).
  962. */
  963. void DumbTest(){
  964.     short a;
  965.     
  966.     a=2;
  967. }
  968.  
  969. #endif
  970.  
  971.  
  972.  
  973.  
  974.  
  975.  
  976.